const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin'); // 自动生成index.html
const MiniCssExtractPlugin = require('mini-css-extract-plugin'); // 文本分离插件，分离js和css
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); // 清理垃圾文件
const CopyWebpackPlugin = require('copy-webpack-plugin');
const OptimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin');
const WebpackBar = require('webpackbar');
const VueLoaderPlugin = require('vue-loader/lib/plugin'); // vue加载器
const HardSourceWebpackPlugin = require('hard-source-webpack-plugin'); // 为模块提供中间缓存

const EnvVariable = require('./src/envVariable/index.js');
const Proxy = require('./persagy_config');
const mockService = require('./mock');

const { ENV } = process.env;

// 前端系统名，影响 打包输出、路由配置、部署 重要，通常与产品名称一致
const SYSTEM_NAME = EnvVariable.SYSTEM_NAME.replace(/"/g, '');

// 获取时间
const TimeFn = require('./get_time');

/**
 *  css和less开发、生产依赖
 *  生产分离css
 */
const cssConfig = [
    ENV !== 'development' ? MiniCssExtractPlugin.loader : 'style-loader',
    {
        loader: 'css-loader',
        options: {
            sourceMap: ENV !== 'production',
            importLoaders: ENV === 'production' ? 1 : 0
        }
    },
    'postcss-loader'
];
const lessConfig = [
    ENV !== 'development' ? {
        loader: MiniCssExtractPlugin.loader,
        options: {
            publicPath: '../'
        }
    } : 'style-loader',
    {
        loader: 'css-loader',
        options: {
            sourceMap: ENV !== 'production',
            importLoaders: ENV === 'production' ? 2 : 0
        }
    },
    {
        loader: 'postcss-loader',
        options: {
            plugins: [
                require('autoprefixer')({
                    overrideBrowserslist: ['last 5 version', '>1%', 'ios 7']
                })
            ]
        }
    },
    {
        loader: 'less-loader',
        options: {
            sourceMap: ENV !== 'production'
        }
    }, {
        loader: 'style-resources-loader',
        options: {
            injector: 'prepend',
            patterns: path.resolve(__dirname, 'src/assets/less/variables.less')
        }
    }
];

const config = {
    entry: {
        main: './src/main.js'
    },
    output: {
        path: path.resolve(__dirname, `${ENV}/${SYSTEM_NAME}`),
        filename: ENV === 'development' ? 'javascript/[name].js' : 'javascript/[name].[hash:8].js',
        publicPath: ENV === 'development' ? '/' : './'
    },
    module: {
        rules: [
            {
                test: /\.css$/,
                use: cssConfig
            },
            {
                test: /\.less$/,
                use: lessConfig,
                include: [path.resolve(__dirname, 'src')]
            },
            {
                test: /\.vue$/,
                use: [
                    'thread-loader',
                    {
                        loader: 'vue-loader',
                        options: {
                            loaders: {
                                css: cssConfig,
                                less: lessConfig
                            },
                            preserveWhitespace: false // 不要留空白
                        }
                    }
                ],
                include: [path.resolve(__dirname, 'src')]
            },
            {
                test: /\.js$/,
                use: [
                    'thread-loader', 'cache-loader',
                    {
                        loader: 'babel-loader',
                        options: {
                            cacheDirectory: ENV !== 'production'
                        }
                    }
                ],
                exclude: (file) => (
                    /node_modules/.test(file) && !/\.vue\.js/.test(file)
                )
            },
            {
                test: /\.svg$/,
                use: ['babel-loader', 'vue-svg-loader'],
                include: [path.resolve(__dirname, 'src')]
            },
            {
                test: /\.html$/,
                use: [
                    {
                        loader: 'html-loader',
                        options: { // 配置html中图片编译
                            minimize: true,
                            attributes: false
                        }
                    }
                ]
            },
            {
                test: /\.(png|jpe?g|gif|bmp)$/,
                use: [
                    {
                        loader: 'url-loader',
                        options: { // 配置图片编译路径
                            limit: 1024, // 小于1k将图片转换成base64
                            name: '[name].[hash:8].[ext]',
                            outputPath: ENV === 'development' ? './' : './images',
                            esModule: false
                        }
                    }
                ],
                include: [path.resolve(__dirname, 'src')]
            }
        ]
    },
    resolve: { // 配置路径别名
        extensions: ['.js', '.vue', '.less'], // import引入文件的时候不用加后缀
        modules: [
            'node_modules',
            path.resolve(__dirname, 'src/assets'),
            path.resolve(__dirname, 'src/envVariable'),
            path.resolve(__dirname, 'src/store'),
            path.resolve(__dirname, 'src/utils'),
            path.resolve(__dirname, 'src/views')
        ],
        alias: {
            '@': path.resolve(__dirname, 'src')
        }
    },
    plugins: [
        new webpack.DefinePlugin({
            process: {
                env: {
                    BASE: EnvVariable
                }
            }
        }),
        new WebpackBar({
            color: '#0091ff'
        }),
        new OptimizeCssAssetsWebpackPlugin({
            canPrint: false
        }),
        new webpack.BannerPlugin(`@persagy ${TimeFn()}`),
        new HardSourceWebpackPlugin(),
        new VueLoaderPlugin(), // vue加载器
        new CopyWebpackPlugin({
            patterns: [{ // 拷贝
                from: path.resolve(__dirname, 'static'),
                to: 'static'
            }, {
                from: path.resolve(__dirname, `node_modules/vue/dist/vue${ENV === 'production' ? '.min' : ''}.js`),
                to: 'modules'
            }, {
                from: path.resolve(__dirname, `node_modules/vuex/dist/vuex${ENV === 'production' ? '.min' : ''}.js`),
                to: 'modules'
            }, {
                from: path.resolve(__dirname, `node_modules/vue-router/dist/vue-router${ENV === 'production' ? '.min' : ''}.js`),
                to: 'modules'
            }]
        }),
        new HtmlWebpackPlugin({
            base: ENV === 'production' ? '' : `/${SYSTEM_NAME}`,
            template: path.join(__dirname, `src/index${ENV === 'production' ? '' : 'Dev'}.html`), // 引入模版
            favicon: path.join(__dirname, 'src/assets/favicon.ico'),
            filename: 'index.html',
            minify: { // 对index.html压缩
                collapseWhitespace: true, // 去掉index.html的空格
                removeAttributeQuotes: ENV === 'production', // 去掉引号
                removeCommentsFromCDATA: ENV === 'production',
                minifyCSS: true,
                removeComments: ENV === 'production'
            },
            hash: true, // 去掉上次浏览器的缓存（使浏览器每次获取到的是最新的html）
            inlineSource: '.(js|css)',
            chunks: 'all'
        }),
        // 插件
        new webpack.ProvidePlugin({
            _: 'lodash'
        })
    ],
    externals: {
        vue: 'Vue',
        vuex: 'Vuex',
        'vue-router': 'VueRouter'
    }
};

if (ENV === 'development') {
    config.devtool = 'eval-source-map';
    config.devServer = {
        before: process.env.IS_MOCK && mockService,
        contentBase: path.join(__dirname, `${ENV}/${SYSTEM_NAME}`),
        compress: true, // 开启Gzip压缩
        host: '0.0.0.0', // 设置服务器的ip地址，默认localhost
        port: 3010, // 端口号
        open: true, // 自动打开浏览器
        openPage: SYSTEM_NAME,
        hot: true,
        overlay: { // 当出现编译器错误或警告时，就在网页上显示一层黑色的背景层和错误信息
            errors: true
        },
        disableHostCheck: true, //  不检查主机
        // 配置服务器代理 处理跨域
        proxy: Proxy,
        // historyApiFallback: true
        historyApiFallback: { // 当使用 HTML5 History API 时，任意的 404 响应都可能需要被替代为 /
            rewrites: [{ from: /./, to: '/' }]
        }
    };
} else {
    config.entry = {
        main: ['core-js/stable', 'regenerator-runtime/runtime', './src/main.js']
    };
    config.plugins.push(
        new CleanWebpackPlugin({
            verbose: true, // 打印被删除的文件
            protectWebpackAssets: false, // 允许删除cleanOnceBeforeBuildPatterns中的文件
            cleanOnceBeforeBuildPatterns: ['**/*', path.resolve(__dirname, ENV)]
        }),
        new MiniCssExtractPlugin({ // 分离css
            filename: 'stylesheets/[name].[contenthash:8].css'
        })
    );

    config.optimization = { // 抽离第三方插件
        // minimize: ENV === 'production',
        minimize: false,
        splitChunks: {
            chunks: 'all',
            minSize: 30000,
            maxSize: 0,
            minChunks: 1,
            maxAsyncRequests: 5,
            maxInitialRequests: 3,
            automaticNameDelimiter: '~',
            name: true,
            cacheGroups: {
                default: false,
                vendors: {
                    name: 'vendors',
                    test: /[\\/]node_modules[\\/]/,
                    minSize: 1000000,
                    maxSize: 1300000,
                    priority: 20
                },
                utils: { // 抽离自定义工具库
                    name: 'utils',
                    minSize: 0,
                    test: /[\\/]src[\\/]utils[\\/]/,
                    priority: 15
                }
            }
        }
    };
}

module.exports = config;
